
/************************************************************************
 *
 * SPRT printer SO for linux;
 * Created by qzfeng 2015/09/09
 *
 ***********************************************************************/

#include <stdio.h>
#include <string.h>
//#include <libusb/include/libusb.h>
#include "HWISPRTPrinter.h"
#include <pthread.h> 
#include <sys/select.h>
#include <time.h>

#include <dirent.h> 
#include <sys/stat.h>
#include <stdlib.h>     /*标准函数库定义*/
#include <unistd.h>     /*Unix 标准函数定义*/
#include <sys/types.h> 
#include <sys/time.h>
#include <sys/stat.h>  
#include <fcntl.h>      /*文件控制定义*/
#include <termios.h>    /*PPSIX 终端控制定义*/
#include <libusb/libusb.h>
#include <errno.h>
#include "serial.h"
#include "bitmap.h"

//-------------ztongli.2016.12.19--------------
AL al;//通用接口整合，内部使用的全局结构体
//-------------ztongli.2016.12.19--------------

libusb_device_handle *gDev_handle=NULL;      // usb开口句柄;
// pthread_mutex_t gPUsb_mutex;						// usb锁;
// pthread_mutex_t gPLog_mutex;						// 日志锁;
libusb_context *gCtx=NULL;	


// 打印机发送指令缓冲区及发送指令长度（字节）;
unsigned char gCmdBuf[1024];
int gCmdBufLen;
// 打印机接收缓冲区及接收返回字节长度;
unsigned char gRcvBuf[1024];
int gRcvBufLen;

char gLogBuf[1024];		// 日志记录缓冲区;

//int socketFd=0;					// 网口句柄,WX_20160811
int serialFd=0;					// 串口句柄; qzfeng 2016/05/11

typedef struct
{
	u_int8_t  bInterfaceNumber;
	u_int8_t  bInEndpointAddress;
	u_int8_t  bOutEndpointAddress;
	u_int16_t idVendor;
	u_int16_t idProduct;       
}stUsbCtrl;

stUsbCtrl usbctrl;				//garland 2019-01-08


#define HWISPR_CALL(theCall) \
    do {                                     \
        int status_; \
        if ((status_ = (theCall)) != 0) {          \
            printf("failed to call "#theCall", status = %d", status_); \
            return status_;                \
        }                                    \
    } while (0)

// 串口开口函数; 返回值: 0 成功，其他失败；
int Sprt_serial_open(char *Dev)
{
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_serial_open() begin...");
	DoLog(gLogBuf,strlen(gLogBuf));

	// pthread_mutex_lock(&gPUsb_mutex);

	InitGlobalVar();

	serialFd = OpenSerialPort(Dev);
    portinfo_t portinfo ={
        '0',                            // print prompt after receiving
        230400,                         // baudrate: 9600
        (char)('0'+8),                            // databit: 8
        '0',                            // debug: off
        '0',                            // echo: off
        '0',                            // flow control: none
        (char)('0'+0),
                                               // parity: none
        (char)('0'+1),                            // stopbit: 1
         0                          // reserved
    };
    printf("baudrate = %d, databit = %c, parify = %c, stopbit = %c\n",
              portinfo.baudrate,
              portinfo.databit,
              portinfo.parity,
              portinfo.stopbit);
    if (serialFd <=0) {
        printf("Open port failed,%s\n",strerror(errno));
		serialFd = -1;
        return ERR_OPEN_FAILED;
    }
    PortSet(serialFd, &portinfo);
	return 0;
}

// 串口关口函数; 返回值: 0 成功，其他失败；
int Sprt_serial_close()
{
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_serial_close() begin...");
	DoLog(gLogBuf,strlen(gLogBuf));

	if(serialFd > 0)
	{
		CloseSerialPort(serialFd);
		// close_dev(serialFd);
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_serial_close() finished.");
		DoLog(gLogBuf,strlen(gLogBuf));
		serialFd = -1;
		return 0;	
	}
	else
	{
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_serial_close() serialFd==-1");
		DoLog(gLogBuf,strlen(gLogBuf));
		return -1;
	}
}

// 串口接收函数; pBufLen为期望接收到的字节个数; 成功：返回值为实际读取的字节数,其他失败;
int Sprt_serial_read(unsigned char *pBuf,int pBufLen,int sleepTime)
{
	if (serialFd < 0) {
		printf("device not open\n");
		return ERR_NOT_OPEN;
	}
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_serial_read() begin...");
	DoLog(gLogBuf,strlen(gLogBuf));	
	
	int ret=-1;
	int count=0;
	int timeout = sleepTime;
	unsigned char tempBuf[1024]={0};
  	int ii=0;
	count=0;
	while (timeout > 0) {
		fd_set fset;
		FD_ZERO(&fset);
		FD_SET(serialFd, &fset);
		struct timeval tm;
		tm.tv_sec = timeout;
		tm.tv_usec = 0;
		ret = select(serialFd+1, &fset, NULL, NULL, &tm);
		timeout = tm.tv_sec*1000+tm.tv_usec/1000;
		if (ret < 0) {
			sprintf(gLogBuf,"select exit, %s\n", strerror(errno));
			DoLog(gLogBuf,strlen(gLogBuf));
			serialFd = -1;
			return ret;
		} else if (ret == 0) {
			sprintf(gLogBuf,"select timeout");
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		} else {
			if (!FD_ISSET(serialFd, &fset)) {
				serialFd = -1;
        		return count;
    		}
			ret = PortRecv(serialFd, (char *)tempBuf, sizeof(tempBuf));
			sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_serial_read() 1 read() ii=%d,ret=%d",ii,ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			if (ret > 0) {
				memcpy((void *)&pBuf[count],(void *)tempBuf,ret);
		  		count+=ret;
			}
		}
		return count;
	}
 	// pthread_mutex_unlock(&gPUsb_mutex);

  	return count;	
}	

// 串口发送函数; 成功：返回值等于pBufLen，其他失败;
int Sprt_serial_write(unsigned char *pBuf,int pBufLen)
{
	if (serialFd < 0) {
		printf("device not open\n");
		return ERR_NOT_OPEN;
	}
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_serial_write() begin...");
	DoLog(gLogBuf,strlen(gLogBuf));
		
	// pthread_mutex_lock(&gPUsb_mutex);
	int ret = -1;

	int send = 0;
    FlushBuffer(serialFd,0);
    FlushBuffer(serialFd,1);
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_serial_write() pBufLen=%d",pBufLen);
	DoLog(gLogBuf,strlen(gLogBuf));

	while (send < pBufLen) {
		int max_len = pBufLen-send >= 8 ?8:(pBufLen-send);
		ret = PortSend(serialFd, (const char *)&pBuf[send], max_len);
		if (ret < max_len) {
			printf("send failed, %d < %d\n", ret, max_len);
			return ERR_SEND_UNFINISHED;
		}
		send += max_len;
	}

	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_serial_write() finished.");
	DoLog(gLogBuf,strlen(gLogBuf));

  	return send;
	
}



// 接口要求实现的函数;
/*****************************************************************************************************/

/* 
 * 功能：打印机切纸;；
 * 入口参数：
 * 					m:切纸方式, 0:全切,1:半切;
 *					n：切纸前走纸n点行,n=0为缺省3点;
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Control_CutPaper(int m,int n)
{
	// 走纸n行
	unsigned char cmd[] = {0x1b, 0x64, n==0? 0x03: ((unsigned char)n)&0xff};
	HWISPR_CALL(SendCmd(cmd, 3));

	// 切纸
	unsigned char cmd2[] = {0x1b, m==1? 0x6d: 0x69};
	HWISPR_CALL(SendCmd(cmd2, 2));
	
	return 0;
}

/* 
 * 功能：打印机进纸（按点）;
 * 入口参数：
 * 					lineDots：进纸点数;
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Control_FeedLines(int lineDots)
{
	// 走纸n行
	unsigned char cmd[] = {0x1b, 0x64, ((unsigned char)lineDots)&0xff};
	HWISPR_CALL(SendCmd(cmd, 3));
	return 0;
}
/* 
 * 功能：初始化打印机状态，清空打印缓冲区 ESC @;
 * 入口参数：
 * 					无;
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Control_ReSet()
{
	unsigned char cmd[] = {0x1b, 0x40};
	return SendCmd(cmd, 2);
}

/* 
 * 功能：设置左边距 ESC $ nL nH （设置成[( nL + nH × 256)  × 横向移动单位)]英寸）;
 * 入口参数：
 * 					pos：距离;
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Control_SetXPosition(int pos)
{
	unsigned int nPos = (unsigned int)pos;
	unsigned char cmd[] = {0x1b, 0x24, nPos&0x000000ff, (nPos>>8)&0x000000ff};
	return SendCmd(cmd, 4);
}

/**
 *   纵向距离设置
 * 
 */
int POS_Control_SetYPosition(int pos)
{
	unsigned char cmd[] = {0x1b, 0x62, 0x01, (unsigned char)pos};
	return SendCmd(cmd, 4);
}

/* 
 * 功能：对齐方式 ESC a n;
 * 入口参数：
 * 					align：0,左对齐，1,居中，2,右对齐;
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Control_AlignType(int align)
{
	unsigned char cmd[] = {0x1b, 0x61, (align&0xff)};
	return SendCmd(cmd, 3);
}


/* 
 * 功能：打印数据并向前走纸若干行 ESC d n;
 * 入口参数：
 * 					lines：行数;
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Output_PrintBuffAndFeedLines(int lines)
{
	unsigned char cmd[] = {0x1b, 0x64, (lines&0xff)};
	return SendCmd(cmd, 3);
}

/* 
 * 功能：按类型实时查询打印机状态；
 * 入口参数：
 * 					n = 1: 传送打印机状态 , n = 2: 传送脱机状态, n = 3: 传送错误状态, n = 4: 传送卷纸传感器状态
 *					flag：端口宏
 * 出口参数：
 *					无;
 * 返回值：
 *					0:正常,101:脱机,102:联机错误,103:进纸键断开,201:钱箱高电平;301：机械错误；302：切纸错误 303：发生不可恢复错误
 *                  401： 打印纸将用完  402: 打印纸已用完
 *					<0: 错误；
 *
 */
int POS_Status_RTQueryTypeStatus(int type)
{
#if 1
	unsigned char cmd[] = {0x1d, 0x72, (type&0xff)};
	int ret = SendCmd(cmd, 3);
	
	if (ret < 0) {
		printf("Send failed, ret =%d\n", ret);
		return ret;
	}

	unsigned char recv[64] = {0};
	int recv_len = RecvCmd(recv, 1);

	if (recv_len <= 0) {
		printf("receive failed, recv_len = %d\n", recv_len);
		return ERR_RECV_FAILED;
	}

	unsigned char b = recv[0];
#else
	unsigned char b = printer_read(serialFd);
#endif

	if (b & 0x04) {
		return ERR_PAPER_USEDOUT;
	} else if (b & 0x80) {
		// 过热
		return ERR_OVERHAET;
	} else {
		return b;
	}
	return 0;
}


/* 
 * 功能：设置打印西文字体;
 * 入口参数：
					flag：端口标志
 * 					isFont：0,压缩字体(9x17)；1,正常字体(12x24);
 * 					isBold：0,正常；1,加粗;
 * 									加粗模式对字符和汉字都有效，除加粗模式外，其他模式只对字符有效。
 * 					isDoubleWidth：0,正常；1,倍宽;
 * 					isDoubleHeight：0,正常；1,倍高;
 * 					isUnderLine：0,正常；1,有下划线;
 *					
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Control_SetPrintFontE(int isFont,
				    									 int isBold,
				    									 int isDoubleWidth,
				    									 int isDoubleHeight,
				    									 int isUnderLine
				    								 )
{
	// 设置字体
	unsigned char font = 0;
	font |=  isFont;
	font |=  isBold<<3;
	font |=  isDoubleHeight<<4;
	font |=  isDoubleWidth<<5;
	font |=  isUnderLine<<7;

	unsigned char cmd_font[] = {0x1b, 0x21, font};
	HWISPR_CALL(SendCmd(cmd_font, 3));  	
	
	return 0;	
  	
}

/**
 *  设置粗体  bold: 0:不加粗, 1:加粗
 * 
 */
int POS_Control_SetBold(int bold)
{
	// 设置粗体
	unsigned char cmd_bold[] = {0x1b, 0x45, bold};	  
	HWISPR_CALL(SendCmd(cmd_bold, 3));
	return 0;
}

int POS_Control_SetModeFontC()
{
	unsigned char cmd[] = {0x1c, 0x26};
	return SendCmd(cmd, 2);
}

/* 
 * 功能：设置汉字字体;
 * 入口参数：
 * 					isDoubleWidth：0,正常；1,倍宽;
 * 					isDoubleHeight：0,正常；1,倍高;
 * 					isUnderLine：0,正常；1,有下划线;
 *					
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Control_SetPrintFontC( int isDoubleWidth, int isDoubleHeight, int isUnderLine)
{
	return 0;
}

int SendCmd(unsigned char cmd[], int len) {
	emptyAttribute(&al);
	al.cmdBuf			=	cmd;
	al.bufLen			=	len;
	int ret					=	writeData(&al);

	if (ret < 0) {
		return ret;
	}

	int cmd_len = len > 256 ? 256:len;
	printf("send:\n");
	for (int i = 0; i < cmd_len; i++) {
		printf("%02X ", cmd[i]);
	}
	printf("\n");

	if(ret!=len)
	{
		sprintf(gLogBuf,"writeData() fail! ret=%d, cmdLen=%d",ret,len);
		DoLog(gLogBuf,strlen(gLogBuf));
		return ERR_SEND_UNFINISHED;
	}	

	sprintf(gLogBuf,"writeData() Success!");
	DoLog(gLogBuf,strlen(gLogBuf));
	
	return 0;	
}

int RecvCmd(unsigned char recv[], int max) {
	int ret = 0;
	// 读取数据；
	emptyAttribute(&al);
	al.cmdBuf		=	recv;
	al.bufLen		=	max;
	ret		=	readData(&al);
	if(ret<=0)
	{
		sprintf(gLogBuf,"readData() fail! ret<=0,ret=%d",ret);
		DoLog(gLogBuf,strlen(gLogBuf));
		return ret;
	}

	int cmd_len = ret > 256 ? 256:ret;
	printf("recv:\n");
	for (int i = 0; i < cmd_len; i++) {
		printf("%02X ", recv[i]);
	}
	printf("\n");
	return ret;
}

// 设置字符大小:  GS ! n
// 字体SIZE: (w<<4+h),   w [0, 7],  h [0, 7]
int POS_Control_SetFontSize(int size)
{
	unsigned char cmd[] = {0x1b, 0x21, size};
	return SendCmd(cmd, 3);
}


int POS_Output_Send_QRCODE(unsigned char pL, unsigned char pH, unsigned char cn, unsigned char fn, int m, unsigned char data[], int len)
{
	int idx = 0;
	unsigned char *cmd = malloc(8+len);
	cmd[idx++] = 0x1d;
	cmd[idx++] = 0x28;
	cmd[idx++] = 0x6b;
	cmd[idx++] = pL;
	cmd[idx++] = pH;
	cmd[idx++] = cn;
	cmd[idx++] = fn;

	if (m != -1) {
		cmd[idx++] = m;
	}
	
	for (int i = 0; i < len; i++) {
		cmd[idx++] = data[i];
	}

	int cmd_len = idx;
	printf("send:\n");
	for (int i = 0; i < cmd_len; i++) {
		printf("%2X ", cmd[i]);
	}
	printf("\n");

	int ret = SendCmd(cmd, cmd_len);
	free(cmd);
	return ret;
}

/* 
 * 功能：打印二维条码;
 * 入口参数：
 * 		条码类型：  
 * 			iType :0: 类型1, n = 1: 类型2
 * 		条码模块大小：
 * 		    m : 条码的模块大小， 1 <= m <= 16, 单位:点
 *      纠错等级:
 *			r：纠错等级， 0：L级(7%)， 1：M级(15%)， 2： Q级(25%)， 3：H级(30%)
 *      条码数据:
 * 			dataStr:表示条码数据
 *					
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Output_PrintBar2code(int iType, int m, int r, unsigned char *dataStr)
{
	// 选型
	unsigned char data1[2] = {0x30+iType, 0x00};
	HWISPR_CALL(POS_Output_Send_QRCODE(0x04, 0x00, 0x31, 0x41, -1, data1, 2));
	
	// 模块大小
	HWISPR_CALL(POS_Output_Send_QRCODE(0x03, 0x00, 0x31, 0x43, m, NULL, 0));

	// 纠错等级
	HWISPR_CALL(POS_Output_Send_QRCODE(0x03, 0x00, 0x31, 0x45, 0x30+r, NULL, 0));

	
	// 下载条码到存储区
	unsigned short len = strlen((const char*)dataStr)+3;
	HWISPR_CALL(POS_Output_Send_QRCODE(len & 0x00ff, (len>>8), 0x31, 0x50, 0x30, dataStr, len-3));

	// 打印qr
	HWISPR_CALL(POS_Output_Send_QRCODE(0x03, 0x00, 0x31, 0x51, 0x30, NULL, 0));
	
	return 0;	
  	
}

/* 
 * 功能：控制钱箱 ESC p m t1 t2;
 * 入口参数：
 * 					m：钱箱号 0 表示钱箱输出插座引脚2， 1 表示钱箱输出插座引脚5;
 * 					t1：脉冲开启的时间为 [ t1 × 2 ms];
 * 					t2：脉冲关闭的时间为 [ t2 × 2 ms];
 * 			  			读入t1、t2,确定本次开钱箱的脉冲宽度;
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Control_CashDraw(int m,int t1,int t2)
{
	return 0;
}

/* 
 * 功能：选择/取消黑白反显打印模式;
 * 入口参数：
 * 					n：0 取消反显打印,1 选择反显打印;
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Control_OppositeColor(int n)
{
	unsigned char cmd[] = {0x1d, 0x42, n&0xff};
	return SendCmd(cmd, 3);
}

/* 
 * 功能：一维条码打印;
 * 入口参数：
 * 			m：条码类型，0 ≤ m ≤ 6 或65 ≤ m ≤ 73 ,详见打印机说明书;
 * 			w：宽度,条码的横向模块宽度：2 ≤ w ≤ 6 对应不同的mm,如：2对应0.25，6对应0.75
 * 			h：高度, 条码纵向点数,1 <=h <= 255, 默认162
 *			n：文字位置; 0 不打印,1 在条码上方打印,2 在条码下方打印,3 条码上、下方都打印;
 * 			hriTextStr：文本信息;
 * 出口参数：
 *			无;
 * 返回值：
 *			0: 正常;
 *			<0: 错误；
 *
 */
int POS_Output_PrintBar1code(int m,int w,int h,int n,unsigned char  *hriTextStr)
{
    
	//发GS W n设置宽度
	unsigned char cmd_width[] = {0x1d, 0x77, w&0xff};
	HWISPR_CALL(SendCmd(cmd_width, 3));

    
    //发GS h n设置高度, n =[10, 240]
	unsigned char cmd_height[] = {0x1d, 0x68, h&0xff};
	HWISPR_CALL(SendCmd(cmd_height, 3));

    //发GS H n设置文字位置
	unsigned char cmd_align[] = {0x1d, 0x48, n&0xff};
	HWISPR_CALL(SendCmd(cmd_align, 3));

	unsigned char  *hriTextStrBytes=hriTextStr;
	int len=strlen((const char*)hriTextStrBytes);

	int idx = 0;
	if((m>=0)&&(m<=8))
	{
        //发GS k m d1...dk nul打印
	    gCmdBuf[idx] = 0x1d;
	    idx++;
	    gCmdBuf[idx] = 0x6b;
	    idx++;
	    gCmdBuf[idx] = (unsigned char)(m&0xff);
	    idx++;
	
	    memcpy((unsigned char *)&gCmdBuf[idx],hriTextStrBytes,len);
	    idx+=len;
	
	    gCmdBuf[idx]=0x00;
	    idx++; 
	
	} else if((m>=65)&&(m<=73)){
		//发GS k m n d1...dn打印
		gCmdBuf[idx] = 0x1d;
		idx++;
		gCmdBuf[idx] = 0x6b;
		idx++;
		gCmdBuf[idx] = (unsigned char)(m&0xff);
		idx++;
		gCmdBuf[idx] = (unsigned char)(len&0xff);
		idx++;
		memcpy((unsigned char *)&gCmdBuf[idx],hriTextStrBytes,len);
		idx+=len;
	}

	return SendCmd(gCmdBuf, idx);
}


/* 
 * 功能：打印一行黑白位图，后面必须再发送回车换行才能打印;
 * 入口参数：
 * 		m:位图模式,0:8点单密度, 1: 8点双密度,32:24点单密度, 33:24点双密度;可选择固定为0；
 * 		n：指令要求位图数据长度(纵向排列，一行一行打印);是横向的点数；如8点就是如果10个字节就是10，如果是24点就是如果是30个字节就是10;
 * 		bytes：位图数据;
 *		bmpByteLength:位图数据字节数；
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Output_PrintBitGraph(int m,int n,unsigned char *bmpByte,int bmpByteLength)
{
	int idx=0;
	int ret=-1;
	
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c POS_Output_PrintBitGraph() begin...");
	DoLog(gLogBuf,strlen(gLogBuf));

	if((m!=0)&&(m!=1)&&(m!=32)&&(m!=33))
	{
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c POS_Output_PrintBitGraph() m is invalid(0,1,32,33)! m=%d",m);
		DoLog(gLogBuf,strlen(gLogBuf));
		return -1;
	}	    	    	
	if(n<0)
	{
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c POS_Output_PrintBitGraph() n<0! n=%d",n);
		DoLog(gLogBuf,strlen(gLogBuf));
		return -2;
	}	    	    	
	
	gCmdBuf[idx] = 0x1b;
	idx++;
	gCmdBuf[idx] = 0x2a;
	idx++;
	gCmdBuf[idx] = (unsigned char)(m&0xff);
	idx++;
	gCmdBuf[idx] = (unsigned char)(n&0xff);
	idx++;
	gCmdBuf[idx] = (unsigned char)((n>>8)&0xff);
	idx++;
	
	memcpy((unsigned char *)&gCmdBuf[idx],bmpByte,bmpByteLength);
	idx+=bmpByteLength;

	gCmdBufLen=idx;
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c POS_Output_PrintBitGraph() ready writeData(),gCmdBuf[]=0x%02x,0x%02x,gCmdBufLen=%d",gCmdBuf[0],gCmdBuf[1],gCmdBufLen);
	DoLog(gLogBuf,strlen(gLogBuf));
	

	//-----------ztongli.2016.12.19-------------
	emptyAttribute(&al);
	al.cmdBuf			=	gCmdBuf;
	al.bufLen			=	gCmdBufLen;
	ret					=	writeData(&al);
	//-----------ztongli.2016.12.19-------------
	//ret=Sprt_net_write(gCmdBuf,gCmdBufLen);

	if(ret!=gCmdBufLen)
	{
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c POS_Output_PrintBitGraph() writeData() fail! ret=%d,gCmdBuf[]=0x%02x,0x%02x,gCmdBufLen=%d",ret,gCmdBuf[0],gCmdBuf[1],gCmdBufLen);
		DoLog(gLogBuf,strlen(gLogBuf));

		return -2;
	}	

	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c POS_Output_PrintBitGraph() writeData() Success!");
	DoLog(gLogBuf,strlen(gLogBuf));
	
	return 0;	
  	
}

/* 
 * 功能：打印用户磁盘上的图像文件；
 * 入口参数：

 *					imagePath: 图像文件路径（若只有文件名则使用当前路径，若指定全路径则使用指定的路径）; 
 * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0:其他错误；
 * 说明：
 *					根据指定的文件路径读取文件，解析出图像信息并打印;
 *					仅支持单色位图文件;
 *					
 */
int POS_Output_PrintBmpDirect(int x, int align, const char *imagePath)
{
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c POS_Output_PrintBmpDirect() imagePath=%s",imagePath);
	DoLog(gLogBuf,strlen(gLogBuf));
	
	int width,  height;
    unsigned char *image_data = load_image(imagePath,  &width,  &height);
    int max_width = 320;
    int chunk_height = 96;  //  考虑到打印机高度、宽度都有限制， 只能分批打印
    int result = -1;

    if (image_data == NULL) {
        printf("load failed, %s\n", imagePath);
        return -1;
    }

	if (width > max_width) {
		printf("width tool big, %d\n", width);
		return -1;
	}
    int byte_width = max_width / 8;

	printf("calculate padding:\n");
    int padding_t, padding_b;
    calculate_padding(height, &padding_t, &padding_b);
    int print_height = height + padding_t + padding_b;

	printf("calculate padding, padding_t = %d, padding_b = %d:\n", padding_t, padding_b);

    unsigned char pixel_bits[byte_width * print_height];

    int c = 0;
    int chunks = 0;
    if (height <= chunk_height) {
        chunks = 1;
    } else {
        chunks = (height /chunk_height) + (height % chunk_height ? 1 : 0);
    }

    while (c < chunks) {
        int chunk = (c + 1) * chunk_height <= height ?
            chunk_height :
            height - (c * chunk_height);

		printf("convert_image_to_bits, chunks = %d, chunk_height = %d:\n",
			chunks, chunk_height);

        int bitmap_w, bitmap_h;
        convert_image_to_bits(
            pixel_bits,
            image_data + (c * chunk_height * width),
            width,
            chunk,
            &bitmap_w,
            &bitmap_h);
		printf("convert_image_to_bits, chunks = %d, chunk_height = %d, w = %d, h = %d:\n",
			chunks, chunk_height, bitmap_w, bitmap_h);

		if (x != 0)
			POS_Control_SetXPosition(x);
		else
    		POS_Control_AlignType(align);

		unsigned char cmd[] = {0x1d, 0x76, 0x30, 0, (((bitmap_w / 8) >> 0) & 0xFF), (((bitmap_w / 8) >> 8) & 0xFF), 
		                       ((bitmap_h >> 0) & 0xFF), ((bitmap_h >> 8) & 0xFF)};
        result = SendCmd(cmd, sizeof(cmd)/sizeof(cmd[0]));	
		result = SendCmd(pixel_bits, (bitmap_w / 8) * bitmap_h);
        if (result != 0) {
			printf("send failed, result = %d\n", result);
            break;
        }
		printf("send success,n = %d, w = %d, h = %d\n", c, bitmap_w, bitmap_h);
        c += 1;
    }

	printf("free gs_image_data\n");
    free(image_data);
	if (result == 0)
		printf("send success\n");
	else
		printf("send failed, result = %d\n", result);
	return result;	
}

/* 
 * 功能：发送给打印机一行字符串;
 * 入口参数：
 * 		printText:字符串以'\0'结尾；注意需以回车换行字符为结束才能立即打印；
  * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Output_PrintString(unsigned char *printText)
{
	int len = strlen((const char*)printText);
	return SendCmd(printText, len);
}

/* 
 * 功能：发送给打印机字节数组;
 * 入口参数：
 * 		printByte:字节数组；
 *    printByteSize:字节数组大小；
  * 出口参数：
 *					无;
 * 返回值：
 *					0: 正常;
 *					<0: 错误；
 *
 */
int POS_Output_PrintData(unsigned char *printByte, int printByteSize)
{
	return SendCmd(printByte, printByteSize);
}
////////////////////////////////////WX_20160908,begin////////////////////////////////////

////////////////////////////////////ESC/POS////////////////////////////////////
/*
	* 功能：旋转打印
	* 入口参数：n(0,不旋转；1,旋转)
	* 出口参数：无
	* 返回值：0（正常）；<0（错误）；
*/
int POS_Control_SetRotaryPrint(int n)
{
	unsigned char cmd[] = {0x1b, 0x56, n&0xff};
	return SendCmd(cmd, 3);
}

/*
	* 功能：倒置打印
	* 入口参数：n(0,不倒置打印；1,倒置打印)
	* 出口参数：无
	* 返回值：0（正常）；<0（错误）；
*/
int POS_Control_SetInvertedPrint(int n)
{
	unsigned char cmd[] = {0x1b, 0x7b, n&0xff};
	return SendCmd(cmd, 3);
}

/*
	* 功能：打印预下载位图
	* 入口参数：n(位图号:0——7)
	* 出口参数：无
	* 返回值：0（正常）；<0（错误）；
*/
int POS_Output_PrintFlashBmp(int n)
{
	unsigned char cmd[] = {0x1c, 0x50, n&0xff};
	return SendCmd(cmd, 3);
}

/*
	* 功能：打印测试页
	* 入口参数：无
	* 出口参数：无
	* 返回值：0（正常）；<0（错误）；
*/
int POS_Control_PrintTestpage()
{
	unsigned char cmd[] = {0x1d, 0x28, 0x41, 0x02, 0x00, 0x00, 0x02};
	return SendCmd(cmd, 3);	
}

/*
	* 功能：设置行高
	* 入口参数：n(行高)
	* 出口参数：无
	* 返回值：0（正常）；<0（错误）；
*/
int POS_Control_SetLineSpace(int n)
{
	unsigned char cmd[] = {0x1b, 0x33, n&0xff};
	return SendCmd(cmd, 3);	
}

/*
	* 功能：黑标定位
	* 入口参数：无
	* 出口参数：无
	* 返回值：0（正常）；<0（错误）；
*/
int POS_Control_BlackMark()
{
	unsigned char cmd[] = {0x0c};
	return SendCmd(cmd, 1);		
}

/*
	* 功能：打印本地文档
	* 入口参数：lpFilePath(本地文档路径)
	* 出口参数：无
	* 返回值：0（正常）；<0（错误）；
*/
int POS_Output_SendLocalFile(unsigned char *lpFilePath)
{
	
	return 0;
}

/*
	* 功能：查询打印任务状态
	* 入口参数：无
	* 出口参数：无
	* 返回值：0（正常）；<0（错误）；
*/
int POS_Status_QueryTaskStatus()
{
	unsigned char cmd[] = {0x1d, 0x28, 0x06, 0x00, 0x30, 0x30, 0x31, 0x32, 0x33, 0x34};
	return SendCmd(cmd, 10);
}

/*
	* 功能：查询打印机ID号
	* 入口参数：无
	* 出口参数：无
	* 返回值：0（正常）；<0（错误）；
*/
int POS_Input_PrinterId(char *buf)
{
	unsigned char cmd[] = {0x1d, 0x49, 0x42};
	return SendCmd(cmd, 3);
}


/////////////////////////////////////TSPL//////////////////////////////////////
// 日志记录函数; 
void DoLog(char *pLogMsg,int logMsgLen)
{

	if((pLogMsg==NULL)||(logMsgLen==0))
	{
		return ;
	}
	printf("%s\n", pLogMsg);

    unsigned char nlineBuf[1024];
	int nlen=strlen(pLogMsg);
	strcpy((char*)nlineBuf,pLogMsg);
	nlineBuf[nlen++]=0x0d;
	nlineBuf[nlen++]=0x0a;

    return;
	unsigned char logPathBuf[256]={0};
//	sprintf(logPathBuf,"%s/log/%s",gOutputDir,LOGFILE);
	sprintf((char*)logPathBuf,"/data/log/%s",LOGFILE);

	FILE *fp=fopen("/data/log/sprtLog.log","ab+");
	if(fp==NULL)
	{
		printf("qzf at DoLog() ab fp==NULL! logPathBuf:%s\r\n", logPathBuf);
		return;
	}		
 	fseek(fp, 0L, SEEK_END);  
  int fileSize = ftell(fp);  
  if(fileSize>MAXLOGFILESIZE)
  {
		printf("qzf at DoLog() fileSize>MAXLOGFILESIZE ! fileSize=%d\r\n",fileSize);
		fclose(fp);
		fp=fopen("/tmp/sprtLog.log","w+");			// 清空日志文件;
		if(fp==NULL)
		{
			printf("qzf at DoLog() w+ fp==NULL!\r\n");
			return;
  	}		
  	fclose(fp);
		return;
	
	}		
	fclose(fp);
    
	time_t timer;				//time_t就是long int 类型
	struct tm *tblock;
	timer = time(NULL);		//这一句也可以改成time(&timer);
	tblock = localtime(&timer);	

	unsigned char tempBuf[512]={0};

	sprintf((char*)tempBuf,"%04d-%02d-%02d %02d:%02d:%02d ",(tblock->tm_year+1900),tblock->tm_mon,tblock->tm_mday,tblock->tm_hour,tblock->tm_min,tblock->tm_sec);
	
	unsigned char lineBuf[1024];
	int len=strlen((const char *)tempBuf);
	strcpy((char *)lineBuf,(const char *)tempBuf);
	lineBuf[len++]='[';
	memcpy((unsigned char *)&lineBuf[len],pLogMsg,logMsgLen);
	len+=logMsgLen;
	lineBuf[len++]=']';
	lineBuf[len++]=0x0d;
	lineBuf[len++]=0x0a;
	
	fp=fopen((const char *)logPathBuf,"a+");
	if(fp==NULL)
	{
		printf("qzf at DoLog() fp==NULL!\r\n");
		return;
  }		
	fwrite(lineBuf,1,len,fp);
	fclose(fp);
	
	return;	
	
}

void InitGlobalVar()
{
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c InitGlobalVar() begin...");
	DoLog(gLogBuf,strlen(gLogBuf));

	gCmdBufLen=0;
	gRcvBufLen=0;
	gCmdBuf[0]=0;
	gCmdBufLen=0;
	gRcvBuf[0]=0;
	gRcvBufLen=0;
	
	// pthread_mutex_init(&gPUsb_mutex,NULL);
	// pthread_mutex_init(&gPLog_mutex,NULL);

	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c InitGlobalVar() finished.");
	DoLog(gLogBuf,strlen(gLogBuf));
	
	return;
}

//2016.12.21.
//端点描述符
// static void print_endpoint(struct libusb_endpoint_descriptor *endpoint)
// {
//   printf("      bEndpointAddress: %xh\n", endpoint->bEndpointAddress);
//   printf("      bmAttributes:     %xh\n", endpoint->bmAttributes);
//   printf("      wMaxPacketSize:   %d\n", endpoint->wMaxPacketSize);
//   printf("      bInterval:        %d\n", endpoint->bInterval);
//   printf("      bRefresh:         %d\n", endpoint->bRefresh);
//   printf("      bSynchAddress:    %d\n", endpoint->bSynchAddress);
// }


// 发送函数; 成功：返回值等于pBufLen，其他失败;
int Sprt_usb_write(unsigned char *pBuf,int pBufLen,int sleepTime)
{
	if(pBufLen<0 || gDev_handle == NULL)
	{
		sprintf(gLogBuf,"Sprt_usb_write() pBufLen<0,pBufLen=%d",pBufLen);
		DoLog(gLogBuf,strlen(gLogBuf));
		return ERR_NOT_OPEN;
	}		
	if(pBufLen==0)
	{
		sprintf(gLogBuf,"Sprt_usb_write() pBufLen=0");
		DoLog(gLogBuf,strlen(gLogBuf));
		return 0;
	}		
	// pthread_mutex_lock(&gPUsb_mutex);

	unsigned char tempBuf[WRITEBYTEMAX]={0};
	int divInt=pBufLen/WRITEBYTEMAX;
	int modInt=pBufLen%WRITEBYTEMAX;
	int i=0;
	int retNum=0;
	int ret=-1;

	for( i=0; i<divInt;i++)
	{
		memcpy(tempBuf,(unsigned char *)&pBuf[i*WRITEBYTEMAX],WRITEBYTEMAX);
		ret=libusb_bulk_transfer(gDev_handle,usbctrl.bOutEndpointAddress, tempBuf,WRITEBYTEMAX, &retNum, sleepTime);
		if((ret !=0)||(retNum!=WRITEBYTEMAX)) 
        {
			sprintf(gLogBuf,"Sprt_usb_write() libusb_bulk_transfer() fail! i=%d,ret=%d,retNum=%d",i,ret,retNum);
			DoLog(gLogBuf,strlen(gLogBuf));

    	    // pthread_mutex_unlock(&gPUsb_mutex);
    	
    	    return ERR_SEND_FAILED;
  	    }
	}
	
	if(modInt!=0)
	{	
		memcpy(tempBuf,(unsigned char *)&pBuf[i*WRITEBYTEMAX],modInt);
		// int templen	=	strlen((const char *)tempBuf);
		// struct libusb_endpoint_descriptor desc;
		// print_endpoint(&desc);
		
		ret=libusb_bulk_transfer(gDev_handle,usbctrl.bOutEndpointAddress, tempBuf,modInt, &retNum, sleepTime);
		//printf("Sprt_usb_write,ret:%d,retNum:%d,sleepTime:%d,templen:%d,",ret,retNum,sleepTime,templen );
		//printf("libusb_error_name:%s\n",libusb_error_name(ret));
		if((ret !=0)||(retNum!=modInt))
        {
			sprintf(gLogBuf,"Sprt_usb_write() libusb_bulk_transfer() fail2! ret=%d,retNum=%d,modInt=%d",ret,retNum,modInt);
			DoLog(gLogBuf,strlen(gLogBuf));

            // pthread_mutex_unlock(&gPUsb_mutex);
    	
            return ERR_SEND_FAILED;
  	    }
    }		
  
	sprintf(gLogBuf,"Sprt_usb_write() finished.");
	DoLog(gLogBuf,strlen(gLogBuf));

 	// pthread_mutex_unlock(&gPUsb_mutex);

    return pBufLen;
	
}
// 接收函数; pBufLen为期望接收到的字节个数; 成功：返回值为实际读取的字节数,其他失败;
int Sprt_usb_read(unsigned char *pBuf,int pBufLen,int sleepTime)
{
	if(pBufLen<0)
	{
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_read() pBufLen<0,pBufLen=%d",pBufLen);
		DoLog(gLogBuf,strlen(gLogBuf));
		return -1;
	}		
	if(pBufLen==0)
	{
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_read() finished. pBufLen=%d",pBufLen);
		DoLog(gLogBuf,strlen(gLogBuf));
		return 0;
	}		
	// pthread_mutex_lock(&gPUsb_mutex);

	int retNum=0;
	int ret=-1;
	
	//---------2016.12.21.ztongli------------
	
	//			发送查询状态的指令到打印机时，执行此第三方库方法libusb_bulk_transfer是获得打印机返回的状态也就是一个字符
	//			此方法第一次执行时从缓冲区内获取不到字符，第二次执行时却接收到两个字符，
	//			推断第一次执行时设置的超时等待比较短，但是增大甚至使用无限超时0时也还是同样的结果
	//			遂使用以下方法暂时将就...待更改
	
	
	unsigned char tmpBuf[1024] = {0};
	
	do
	{
		int recv_len = 0;
		ret=libusb_bulk_transfer(gDev_handle,usbctrl.bInEndpointAddress, tmpBuf,sizeof(tmpBuf), &recv_len, 0);
		retNum += recv_len;
		
	}while(ret>= 0 && retNum < pBufLen);
	
	memcpy(pBuf,tmpBuf,retNum);
	
	//printf("Sprt_usb_read,ret:%d,retNum:%d,pBufLen:%d,",ret,retNum,pBufLen);
	//printf("libusb_error_name:%s\n",libusb_error_name(ret));
	
	//int i;
	//for(i=0;i < sizeof(tmpBuf);i++)
	//{
	//	printf("\r\r\r\r\r\r%d\n",(int)tmpBuf[i]);
	//}
	//---------2016.12.21.ztongli------------
	
	
//	if((ret !=0)||(retNum!=pBufLen)) 
	if((ret !=0)) 
  {
		sprintf(gLogBuf,"Sprt_usb_read() read fail! ret=%d,retNum=%d,pBufLen=%d",ret,retNum,pBufLen);
		DoLog(gLogBuf,strlen(gLogBuf));

  	// pthread_mutex_unlock(&gPUsb_mutex);
  	
  	return ERR_RECV_FAILED;
	}

	if ((retNum < pBufLen)) {
		printf("recv unfinished\n");
		return ERR_RECV_UNFINISHED;
	}

	sprintf(gLogBuf,"Sprt_usb_read() finished. retNum=%d,pBuf[0]=%02x",retNum,pBuf[0]);
	DoLog(gLogBuf,strlen(gLogBuf));
  	return retNum;	
}	

static int FindEndpoint(u_int8_t * bInAddress,u_int8_t *bOutAddress,const struct libusb_interface_descriptor *interface)
{
	sprintf(gLogBuf,"FindEndpoint Begin ... interface->bNumEndpoints = %d",interface->bNumEndpoints);
	DoLog(gLogBuf,strlen(gLogBuf));

	int i;
	int ret=0;
	for(i = 0; i < interface->bNumEndpoints; i++)
	{
		sprintf(gLogBuf,"FindEndpoint A bmAttributes = %02x",interface->endpoint[i].bmAttributes);
		DoLog(gLogBuf,strlen(gLogBuf));

		if((interface->endpoint[i].bmAttributes & 0x03) == 0x02)
		{
			if(interface->endpoint[i].bEndpointAddress & 0x80)
			{
				sprintf(gLogBuf,"FindEndpoint B bEndpointAddress = %02x",interface->endpoint[i].bEndpointAddress);
				ret|=1;
				*bInAddress=interface->endpoint[i].bEndpointAddress;
			}
			else
			{
				sprintf(gLogBuf,"FindEndpoint C bEndpointAddress = %02x",interface->endpoint[i].bEndpointAddress);
				ret|=2;
				*bOutAddress=interface->endpoint[i].bEndpointAddress;
			}
			DoLog(gLogBuf,strlen(gLogBuf));
		}								
	}
	if(ret==3){
		sprintf(gLogBuf,"FindEndpoint End Success ret = %d",ret);
		DoLog(gLogBuf,strlen(gLogBuf));
		return 1;
	}else{
		sprintf(gLogBuf,"FindEndpoint End Fail ret = %d",ret);
		DoLog(gLogBuf,strlen(gLogBuf));
		return 0;
	}
}

int FindInterface(struct libusb_device_descriptor * desc,libusb_device *dev )
{
	sprintf(gLogBuf,"FindInterface() Ready To Find Interface Info !");
	DoLog(gLogBuf,strlen(gLogBuf));

	struct libusb_config_descriptor *conf_desc;
	int i,j,k;
	int isFind = 0; 
	
	u_int8_t  bInterfaceNumber;
	u_int8_t  bInEndpointAddress;
	u_int8_t  bOutEndpointAddress; 
    
	sprintf(gLogBuf, "FindInterface A desc->bNumConfigurations = %d",desc->bNumConfigurations);
	DoLog(gLogBuf,strlen(gLogBuf));

    for (i=0; i< desc->bNumConfigurations; i++) 
    {
    	libusb_get_config_descriptor(dev, i, &conf_desc); 
		sprintf(gLogBuf, "FindInterface B conf_desc->bNumInterfaces = %d",conf_desc->bNumInterfaces);
		DoLog(gLogBuf,strlen(gLogBuf));

		for (j=0; j< conf_desc->bNumInterfaces; j++)
		{				
			sprintf(gLogBuf, "FindInterface C conf_desc->interface[j].num_altsetting = %d",conf_desc->interface[j].num_altsetting);
			DoLog(gLogBuf,strlen(gLogBuf));
			for (k=0; k< conf_desc->interface[j].num_altsetting; k++) 
			{
				sprintf(gLogBuf, "FindInterface D bInterfaceClass = %02x bInterfaceSubClass = %02x",
							conf_desc->interface[j].altsetting[k].bInterfaceClass,conf_desc->interface[j].altsetting[k].bInterfaceSubClass);
				DoLog(gLogBuf,strlen(gLogBuf));

				//if(conf_desc->interface[j].altsetting[k].bInterfaceClass == 0xff && conf_desc->interface[j].altsetting[k].bInterfaceSubClass == 0xff)
				//{
					if(FindEndpoint(&bInEndpointAddress,&bOutEndpointAddress,&(conf_desc->interface[j].altsetting[k])))
					{
						bInterfaceNumber = conf_desc->interface[j].altsetting[k].bInterfaceNumber;

						sprintf(gLogBuf, "FindEndpoint bInEndpointAddress = %02x bOutEndpointAddress = %02x bInterfaceNumber = %02x",
														bInEndpointAddress,bOutEndpointAddress,bInterfaceNumber);
						DoLog(gLogBuf,strlen(gLogBuf));

						libusb_free_config_descriptor(conf_desc);
						isFind = 1;
						goto DINFINTERFACE;
					}
				//}				
			}
		}
		libusb_free_config_descriptor(conf_desc);
    }
DINFINTERFACE :
	if(isFind){
		usbctrl.bInEndpointAddress = bInEndpointAddress;
		usbctrl.bOutEndpointAddress = bOutEndpointAddress;
		usbctrl.bInterfaceNumber = bInterfaceNumber;
		usbctrl.idVendor = desc->idVendor ;
		usbctrl.idProduct = desc->idProduct;
		return 1;
	}else{
		return 0;
	} 
}

//查找USB端点
int GetEndPoint(libusb_device **devs)
{
	sprintf(gLogBuf,"GetEndPoint() Ready To Get Device Info!");
	DoLog(gLogBuf,strlen(gLogBuf));

    libusb_device *dev;
    int i = 0;
	int nRet = 0;

    while ((dev = devs[i++]) != NULL) {
        struct libusb_device_descriptor desc;
        int r = libusb_get_device_descriptor(dev, &desc);
        if (r < 0) {
            sprintf(gLogBuf, "GetEndPoint() failed to get device descriptor");
			DoLog(gLogBuf,strlen(gLogBuf));
            return nRet;
        }

        sprintf(gLogBuf,"GetEndPoint : %04x:%04x (bus %d, device %d)\n",desc.idVendor, desc.idProduct,
            											libusb_get_bus_number(dev), libusb_get_device_address(dev));
		DoLog(gLogBuf,strlen(gLogBuf));
		if (desc.idVendor == VID && desc.idProduct == PID){
			sprintf(gLogBuf,"GetEndPoint : %04x:%04x (bus %d, device %d)\n",desc.idVendor, desc.idProduct,
            											libusb_get_bus_number(dev), libusb_get_device_address(dev));
			DoLog(gLogBuf,strlen(gLogBuf));

			if (FindInterface(&desc,dev)){
				sprintf(gLogBuf, "FindInterface() EndPointIn = %02x EndPointOut = %02x",
										usbctrl.bInEndpointAddress,usbctrl.bOutEndpointAddress);
				DoLog(gLogBuf,strlen(gLogBuf));
				nRet = 1;
			}else{
				sprintf(gLogBuf,"FindInterface Failed!");
				DoLog(gLogBuf,strlen(gLogBuf));
			}
			break;
		}
    }
	sprintf(gLogBuf,"GetEndPoint() Finish Get Device Info!");
	return nRet;
}

// 开口函数; 返回值: 0 成功，其他失败；
int Sprt_usb_open()
{
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_open() begin...");
	DoLog(gLogBuf,strlen(gLogBuf));

	// pthread_mutex_lock(&gPUsb_mutex);

	libusb_device **devs;											//pointer to pointer of device, used to retrieve a list of devices
//	libusb_device_handle *dev_handle;					//a device handle
	int ret=-1;																//for return values
	ssize_t cnt;															//holding number of devices in list
	ret = libusb_init(&gCtx);									//initialize the library for the session we just declared
 
	if(ret <0)
	{
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_open() libusb_init() fail! ret=%d",ret);
		DoLog(gLogBuf,strlen(gLogBuf));
 		
 		// pthread_mutex_unlock(&gPUsb_mutex);
		return ERR_PERMISSION_DENY;
	}
	
	// libusb_set_debug(gCtx, 3);									//set verbosity level to 3, as suggested in the documentation
 
	cnt = libusb_get_device_list(gCtx,&devs);	//get the list of devices
	if(cnt <0){
		sprintf(gLogBuf,"libusb_get_device_list() fail! cnt = %d", (int)cnt);
		DoLog(gLogBuf,strlen(gLogBuf));
 
 		// pthread_mutex_unlock(&gPUsb_mutex);
		return ERR_NOT_FOUND;
	}
 
	//查找USB设备端点，包括EndPointIn 和 EndPointOut
	if (!GetEndPoint(devs)){
		sprintf(gLogBuf,"garland HWISPRTPrinter.c Sprt_usb_open() GetEndPoint() Failed!");
		DoLog(gLogBuf,strlen(gLogBuf));
		return ERR_DEV_NOT_FOUND;
	}

	gDev_handle = libusb_open_device_with_vid_pid(gCtx,VID,PID);		//these are vendorID and productID I found for my usb device
	if(gDev_handle ==NULL)
	{
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_open() libusb_open_device_with_vid_pid() fail! gDev_handle==NULL");
		DoLog(gLogBuf,strlen(gLogBuf));

 		// pthread_mutex_unlock(&gPUsb_mutex);
		return ERR_NOT_FOUND;
	}	
  
  libusb_free_device_list(devs, 1);				//free the list, unref the devices in it
 
 	ret=libusb_kernel_driver_active(gDev_handle,0);
  if(ret==1)
  {			//find out if kernel driver is attached
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_open() libusb_kernel_driver_active() ret=%d",ret);
		DoLog(gLogBuf,strlen(gLogBuf));

		ret=libusb_detach_kernel_driver(gDev_handle,0);
		if(ret==0)			//detach it
		{
			sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_open() libusb_detach_kernel_driver()ret=%d",ret);
			DoLog(gLogBuf,strlen(gLogBuf));

		}		
  }
  ret = libusb_claim_interface(gDev_handle,0);							//claim interface 0 (the first) of device (mine had jsut 1)
	if(ret <0){
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_open() libusb_claim_interface() fail! ret<0,ret=%d",ret);
		DoLog(gLogBuf,strlen(gLogBuf));

 		// pthread_mutex_unlock(&gPUsb_mutex);
		return ERR_DRVIVER_ERROR;
	}

	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_open() finished.");
	DoLog(gLogBuf,strlen(gLogBuf));

	// pthread_mutex_unlock(&gPUsb_mutex);
	return 0;
	
}

// 关口函数; 返回值: 0 成功，其他失败；
int Sprt_usb_close()
{
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_close() begin...");
	DoLog(gLogBuf,strlen(gLogBuf));

	if(gDev_handle!=NULL)
	{
		int ret = libusb_release_interface(gDev_handle,0);	//release the claimed interface
		if(ret!=0){
			sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_close() ret!=0,ret=%d,gDev_handle=%p",ret,gDev_handle);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ERR_DRVIVER_ERROR;
		}
		libusb_close(gDev_handle);//close the device we opened
		libusb_exit(gCtx);//needs to be called to end the
		gDev_handle = NULL;
	}
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_usb_close() finished.");
	DoLog(gLogBuf,strlen(gLogBuf));

	return 0;
}

/**
////////////////////////////////////////////////////////////////网口函数实现,WX_20160811,Begin////////////////////////////////////////////////
// 网口开口函数; 返回值: 0 成功，其他失败；
int Sprt_net_open(char *ipAddress)
{

    //创建用于internet的流协议(TCP)socket,用socketFd代表客户机socket
    socketFd = socket(AF_INET, SOCK_STREAM, 0);
    sprintf(gLogBuf,"socketFd=%d",socketFd);
    DoLog(gLogBuf,strlen(gLogBuf));
    if (socketFd < 0)
    {
        printf("Create Socket Failed!\n");
        return -1;
    }
 
    //设置一个socket地址结构server_addr,代表服务器的internet地址, 端口
    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;

    //char *pIp="192.168.1.114";
    char *pIp=ipAddress;
    if (inet_aton(pIp, &server_addr.sin_addr) == 0) //服务器的IP地址来自程序的参数
    {
        printf("Server IP Address Error! \n");
        return -1;
    }
 
    server_addr.sin_port = htons(SERVER_PORT);
    socklen_t server_addr_length = sizeof(server_addr);
    // 向服务器发起连接,连接成功后socketFd代表了客户机和服务器的一个socket连接

    int ret=connect(socketFd, (struct sockaddr*) &server_addr,
            server_addr_length) ;
    printf("ret=%d\n",ret);
    if (ret < 0)
    {
        printf("Can Not Connect ! \n");
        return -1;
    }
    sprintf(gLogBuf,"socketFd=%d",socketFd);
    DoLog(gLogBuf,strlen(gLogBuf));
    return 0;
}
// 网口关口函数; 返回值: 0 成功，其他失败；
int Sprt_net_close()
{
	sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_net_close() begin...");
	DoLog(gLogBuf,strlen(gLogBuf));

	if(socketFd!=-1)
	{
		close(socketFd);
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_net_close() finished.");
		DoLog(gLogBuf,strlen(gLogBuf));
		return 0;	
	}
	else
	{
		sprintf(gLogBuf,"qzf at HWISPRTPrinter.c Sprt_net_close() socketFd==-1");
		DoLog(gLogBuf,strlen(gLogBuf));
		return -1;
	}		


}
// 网口接收函数; pBufLen为期望接收到的字节个数; 成功：返回值为实际读取的字节数,其他失败;
int Sprt_net_read(unsigned char *pBuf,int pBufLen)
{
	
	int bytes_left;
	int bytes_read;
	//char *pBuf;
   
	bytes_left=pBufLen;
	while(bytes_left>0)
	{
		sprintf(gLogBuf,"socketFd=%d",socketFd);
		DoLog(gLogBuf,strlen(gLogBuf));

   		bytes_read=read(socketFd,pBuf,bytes_left);

		sprintf(gLogBuf,"bytes_read=%d",bytes_read);
		DoLog(gLogBuf,strlen(gLogBuf));
  		if(bytes_read<0)
   		{
			if(errno==EINTR)
      	 		bytes_read=0;
    			else
       	 		return(-1);
  	 	}
  	 	else if(bytes_read==0)
      	 	break;
    		bytes_left-=bytes_read;
   	 	pBuf+=bytes_read;
	}
	sprintf(gLogBuf,"pBuf[0]=%02x",pBuf[0]);
	DoLog(gLogBuf,strlen(gLogBuf));
	return(pBufLen-bytes_left);
	
}
// 网口发送函数; 成功：返回0，其他失败;
int Sprt_net_write(unsigned char *pBuf,int pBufLen)

{
	int bytes_left;
	int written_bytes;
	char *ptr;
 
	ptr=pBuf;
	bytes_left=pBufLen;
	//written_bytes=send(socketFd,ptr,bytes_left,0);
	//sprintf(gLogBuf,"written_bytes=%d,socketFd=%d,bytes_left=%d",written_bytes,socketFd,bytes_left);
	//DoLog(gLogBuf,strlen(gLogBuf));
	while(bytes_left>0)
	{
        	//开始写
        	written_bytes=write(socketFd,ptr,bytes_left);
		//written_bytes=send(socketFd,ptr,bytes_left,0);
		sprintf(gLogBuf,"written_bytes=%d",written_bytes);
		DoLog(gLogBuf,strlen(gLogBuf));
        	if(written_bytes<=0) //出错了
        	{       
                	if(errno==EINTR) //中断错误 我们继续写
                        	written_bytes=0;
               		else             //其他错误 没有办法,只好撤退了
                        	return(-1);
        	}
        	bytes_left-=written_bytes;
        	ptr+=written_bytes;     // 从剩下的地方继续写
	}

	return(pBufLen);

}
////////////////////////////////////////////////////////////////网口函数实现,WX_20160811,Een

**/

//------------------2016.12.19.ztongli----------------
//打开端口
int OpenPort(int port, char* parameter)
{
	
	int ret			=	-1;
	int isParam		=	1;
	if(parameter == NULL)
	{
		isParam		=	0;
	}
	
	
	switch(port)
	{
	case USB_PORT:
		ret			=	Sprt_usb_open();
		if( ret<0)
		{	
			printf("libusb_error_name:%s\n",libusb_error_name(ret));
			sprintf(gLogBuf,"HWISPRTPrinter.c OpenPort() Sprt_usb_open() fail ret=%d",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		printf("Sprt_usb_open() ok ret=%d\n",ret);
		break;
	case SERIAL_PORT:
		if(!isParam)
		{
			//printf("When the port is a serial port, the parameter cannot be empty\n");
			sprintf(gLogBuf,"When the port is a serial port, the parameter cannot be empty");
			DoLog(gLogBuf,strlen(gLogBuf));
			return -1;
		}
		//printf("parameter:%s\n",parameter);
		ret			=	Sprt_serial_open(parameter);
		if( ret<0)
		{	
			//printf("Sprt_serial_open() fail ret=%d\n",ret);
			sprintf(gLogBuf,"Sprt_serial_open() fail ret=%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		//printf("Sprt_serial_open() ok ret=%d\n",ret);
		sprintf(gLogBuf,"Sprt_serial_open() ok ret=%d\n",ret);
		DoLog(gLogBuf,strlen(gLogBuf));
		break;
	/**case NET_PORT:
		if(!isParam)
		{
			//printf("When the port is a net port, the parameter cannot be empty\n");
			sprintf(gLogBuf,"When the port is a net port, the parameter cannot be empty");
			DoLog(gLogBuf,strlen(gLogBuf));
			return -1;
		}
		//printf("parameter:%s\n",parameter);
		ret			=	Sprt_net_open(parameter);
		if( ret<0)
		{	
			//printf("Sprt_net_open() fail ret=%d\n",ret);
			sprintf(gLogBuf,"Sprt_net_open() fail ret=%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		//printf("Sprt_net_open() ok ret=%d\n",ret);
		sprintf(gLogBuf,"Sprt_net_open() ok ret=%d\n",ret);
		DoLog(gLogBuf,strlen(gLogBuf));
		break;**/
	default:
		printf("Please enter port macros\n");
		return -5;
	}
	setAttribute(port);
	
	return ret;
}


//关闭端口
int ClosePort()
{
	int ret			=	-1;
	switch(al.flag)
	{
	case USB_PORT:
		ret=Sprt_usb_close();
		if( ret<0)
		{	
			//printf("Sprt_usb_close() fail ret=%d\n",ret);
			sprintf(gLogBuf,"Sprt_usb_close() fail ret=%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		else
		{
			//printf("Sprt_usb_close() ok ret=%d\n",ret);
			sprintf(gLogBuf,"Sprt_usb_close() ok ret=%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
		}	
		break;
	case SERIAL_PORT:
		ret=Sprt_serial_close();
		if( ret<0)
		{	
			//printf("Sprt_serial_close() fail ret=%d\n",ret);
			sprintf(gLogBuf,"Sprt_serial_close() fail ret=%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		else
		{
			//printf("Sprt_serial_close() ok ret=%d\n",ret);
			sprintf(gLogBuf,"Sprt_serial_close() ok ret=%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
		}			
		break;
	/**case NET_PORT:
		ret=Sprt_net_close();
		if( ret<0)
		{	
			//printf("Sprt_net_close() fail ret=%d\n",ret);
			sprintf(gLogBuf,"Sprt_net_close() fail ret=%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		else
		{
			//printf("Sprt_net_close() ok ret=%d\n",ret);
			sprintf(gLogBuf,"Sprt_net_close() ok ret=%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
		}			
		break;**/
	default:
		printf("Please enter port macros\n");
		return -5;
	}

	return ret;
}

//发送数据
int writeData(AL* attr)
{
	if(attr->cmdBuf == NULL)
	{
		//printf("attr is not null\n");
		sprintf(gLogBuf,"writeData attr->cmdBuf null");
		DoLog(gLogBuf,strlen(gLogBuf));
		return -1;
	}
	if(attr->bufLen == 0)
	{
		attr->bufLen		=	strlen((const char *)attr->cmdBuf);
	}

	int ret			=	-1;
	switch(attr->flag)
	{
	case USB_PORT:
		ret			=	Sprt_usb_write(attr->cmdBuf,attr->bufLen,attr->sleepTime = 1000);
		if(ret < 0)
		{
			//printf("Sprt_usb_write err:%d\n",ret);
			sprintf(gLogBuf,"Sprt_usb_write err:%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		//printf("Sprt_usb_write OK\n");
		break;
	case SERIAL_PORT:
		ret			=	Sprt_serial_write(attr->cmdBuf,attr->bufLen);
		if(ret < 0)
		{
			//printf("Sprt_serial_write err:%d\n",ret);
			sprintf(gLogBuf,"Sprt_serial_write err:%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		//printf("Sprt_serial_write OK\n");
		break;
	/**case NET_PORT:
		ret			=	Sprt_net_write(attr->cmdBuf,attr->bufLen);
		if(ret < 0)
		{
			//printf("Sprt_net_write err:%d\n",ret);
			sprintf(gLogBuf,"Sprt_net_write err:%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		//printf("Sprt_net_write OK\n");
		break;**/
	default:
		printf("Please enter port macros\n");
		return -5;
	}

	return ret;
}

//读取数据
int readData(AL* attr)
{
	if(attr->cmdBuf == NULL)
	{
		//printf("attr.cmdBuf is not null\n");
		sprintf(gLogBuf,"readData attr->cmdBuf null");
		DoLog(gLogBuf,strlen(gLogBuf));
		return -1;
	}
	
	int ret			=	-1;
	switch(attr->flag)
	{
	case USB_PORT:
		ret			=	Sprt_usb_read(attr->cmdBuf,attr->bufLen,attr->sleepTime = 10);
		if(ret < 0)
		{
			//printf("Sprt_usb_read err:%d\n",ret);
			sprintf(gLogBuf,"Sprt_usb_read err:%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		else if(ret == 0)
		{
			//printf("Sprt_usb_read not data ret:%d\n",ret);
			sprintf(gLogBuf,"Sprt_usb_read not data ret:%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		//printf("Sprt_usb_read OK\n");
		break;
	case SERIAL_PORT:
		ret			=	Sprt_serial_read(attr->cmdBuf,attr->bufLen,attr->sleepTime = 5);
		if(ret < 0)
		{
			//printf("Sprt_serial_read err:%d\n",ret);
			sprintf(gLogBuf,"Sprt_serial_read err:%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		else if(ret == 0)
		{
			//printf("Sprt_serial_read not data ret:%d,sleepTime:%d\n",ret,attr->sleepTime);
			sprintf(gLogBuf,"Sprt_serial_read not data ret:%d,sleepTime:%d\n",ret,attr->sleepTime);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		//printf("Sprt_serial_read OK\n");
		break;
	/**case NET_PORT:
		ret			=	Sprt_net_read(attr->cmdBuf,attr->bufLen);
		if(ret < 0)
		{
			//printf("Sprt_net_read err:%d\n",ret);
			sprintf(gLogBuf,"Sprt_net_read err:%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		else if(ret == 0)
		{
			//printf("Sprt_net_read not data ret:%d\n",ret);
			sprintf(gLogBuf,"Sprt_net_read not data ret:%d\n",ret);
			DoLog(gLogBuf,strlen(gLogBuf));
			return ret;
		}
		//printf("Sprt_net_read OK\n");
		break;**/
	default:
		printf("Please enter port macros\n");
		return -5;
	}

	return ret;
}

//设置端口宏
int setAttribute(int port)
{
	emptyAttribute(&al);
	if(port == USB_PORT || port == SERIAL_PORT || port == NET_PORT)
	{
		al.flag		=	port;
		return 0;
	}
	printf("Please enter port macros\n");
	return -1;
}

//清空全局AL结构体的个别成员
void emptyAttribute(AL* attr)
{
	attr->cmdBuf		=	NULL;
	attr->bufLen		=	0;
	attr->sleepTime		=	0;
}


//--------2016.12.13.ztongli
int  QueryErrState()
{
	
	unsigned char cmd[]				= {0x10,0x04,0x03,0};
	int BufLen				= strlen((const char *)cmd);
	int res						= -1;
	//-----------ztongli.2016.12.20-------------
	emptyAttribute(&al);
	al.cmdBuf			=	cmd;
	al.bufLen			=	BufLen;
	res					  =	writeData(&al);
	//-----------ztongli.2016.12.20-------------
	//int res 					= Sprt_serial_write(cmd,BufLen);
	
	/*printf("Sprt_serial_write:%d,cmd:%d\n",res,(int)cmd[0]);
	printf("Sprt_serial_write:%d,cmd:%d\n",res,(int)cmd[1]);
	printf("Sprt_serial_write:%d,cmd:%d\n",res,(int)cmd[2]);*/
	
	unsigned char ResState[3]  = {0};
	
	if(res == BufLen)
	{
				//--------------2016.12.20.ztongli--------------
				emptyAttribute(&al);
				al.cmdBuf		=	ResState;
				al.bufLen		=	1;
				res		=	readData(&al);
				//--------------2016.12.20.ztongli--------------
				//res						=	Sprt_serial_read(ResState,1,5);
				
				if(res != 1)
				{
					return -3;
				}   
 				//printf("res:%d,str:%x,strlen:%d\n",res,(int)ResState[0],strlen(ResState));	
 				int bin				=	(int)ResState[0];
 				//int bin	= (int)0x72;
 				if(bin == 18)//00010010
 				{
 						return 0;
 						//return "无不可恢复错误&没有自动恢复错误";
 				}
 				else if(bin == 50)//00110010
 				{
 						return 1;
 						//return "有不可恢复错误";
 				}
 				else if(bin == 82)//01010010
 				{
 						return 2;
 						//return "有自动恢复错误出现";
 				}
 				else if(bin == 114)//01110010
 				{
 						return 3;
 						//return "有自动恢复错误出现&有不可恢复错误";
 				}
	}

	return -1;
}
